package com.glsc.ngateway.opmanage.service.deposit;

import com.glsc.ngateway.common.api.common.utils.DateUtil;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.DepositoryBank;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.DepositoryBaseDataQuarter;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.DepositoryBaseDataYear;
import com.glsc.ngateway.common.base.repo.mysql.opmanagemain.deposit.DepositoryBaseDataYearRepository;
import com.glsc.ngateway.opmanage.dto.DepositoryBaseDataExcelDto;
import com.glsc.ngateway.opmanage.utils.SpecificationUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.opmanage.utils.report.ReportFileUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportUploadContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

@Service
public class DepositoryBaseDataYearService {


    @Resource
    private DepositoryBaseDataYearRepository baseDataYearRepository;

    @Resource
    private DepositoryBankService bankService;

    /**
     * 分页查找
     *
     * @param pageNo
     * @param pageSize
     * @param param
     * @return
     */
    public Page<DepositoryBaseDataYear> page(int pageNo, int pageSize, Map<String, Object> param) {
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "createTime";

        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        Page<DepositoryBaseDataYear> page = baseDataYearRepository.findAll(SpecificationUtil.buildSpecification(param, DepositoryBaseDataYear.class), pageable);

        return page;
    }

    /**
     * 根据id查找
     *
     * @param id
     * @return
     */
    public DepositoryBaseDataYear findById(Integer id) {
        Optional<DepositoryBaseDataYear> optional = baseDataYearRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        }
        return null;
    }

    /**
     * 保存
     *
     * @param obj
     * @return
     */
    public DepositoryBaseDataYear save(DepositoryBaseDataYear obj) {
        if (Objects.isNull(obj.getBankId())) {
            if (StringUtils.isNotBlank(obj.getBankName())) {
                DepositoryBank bank = bankService.findByName(obj.getBankName());
                if (Objects.nonNull(bank)) {
                    obj.setBankId(bank.getId());
                }
            }
        }

        if (Objects.nonNull(obj.getBankId())) {
            DepositoryBank bank = bankService.findById(obj.getBankId());
            obj.setBankName(bank.getBankName());
            //设置生效日期
            //obj.setEffectDate(DateUtil.getNowDateString());
            //设置利率
            if (Objects.isNull(obj.getInterestRate())) {
                obj.setInterestRate(bank.getInterestRate());
            }
            //均值存放比
            obj.setAverageStowageRatio(obj.getAverageBankBalance().divide(obj.getAverageMargin(), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
            //增加10%保证金所需金额（元）
            obj.setIncrease10pMargin(obj.getAverageMargin().multiply(BigDecimal.valueOf(0.1)));

            //单日成本未上传则计算单日成本  平均利率 x 增加10%保证金所需对应金额
            if (Objects.isNull(obj.getOneDayCost())) {
                obj.setOneDayCost(obj.getInterestRate().multiply(obj.getIncrease10pMargin()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
            }

            //可支配金额（安全值）（元）
            obj.setSafeValue(obj.getAverageBankBalance().subtract(obj.getEstimatedMaxDeposits()));

            //如有存放要求，按存放要求计算,无存放要求则等于 预估最低存放最大值（剔除）（元）
            if (Objects.isNull(obj.getIntendedDeposit())) {
                obj.setIntendedDeposit(obj.getEstimatedMaxDeposits());
            }

            //可支配金额（考虑影响因素）=均值银行余额（元）实有-拟定存放（手工调整后）
            obj.setSafeValueInf(obj.getAverageBankBalance().subtract(obj.getIntendedDepositHand()));

            //拟定存放比
            obj.setIntendedDepositHandInf(obj.getIntendedDeposit().divide(obj.getAverageMargin(), 2, RoundingMode.HALF_UP));
        }
        obj.setDeleted("N");
        return baseDataYearRepository.save(obj);
    }

    /**
     * 根据id删除
     *
     * @param id
     */
    public void delete(Integer id) {
        baseDataYearRepository.deleteById(id);
    }


    @Transactional
    public ReportUploadContext<DepositoryBaseDataExcelDto, String> important(MultipartFile file) throws IOException {
        ReportUploadContext<DepositoryBaseDataExcelDto, String> context = ReportUploadContext.<DepositoryBaseDataExcelDto, String>builder().config(ReportFileConfigEnum.DEPOSITORY_BASE_DATE_QUARTER).file(file).build();

        ReportFileUtil.readSingleExcel(context);
        Assert.notEmpty(context.getReadRes(), "上传内容不可为空");


        List<DepositoryBaseDataExcelDto> readResList = context.getReadRes();
        if (CollectionUtils.isEmpty(readResList)) {
            return context;
        }

        for (DepositoryBaseDataExcelDto dto : readResList) {
            DepositoryBaseDataYear year = DepositoryBaseDataYear.builder().averageMargin(dto.getAverageMargin()).averageBankBalance(dto.getAverageBankBalance()).depositFloor(dto.getDepositFloor())
                    .estimatedMinDeposits(dto.getEstimatedMinDeposits()).estimatedMaxDeposits(dto.getEstimatedMaxDeposits()).intendedDeposit(dto.getIntendedDeposit())
                    .intendedDepositHand(dto.getIntendedDepositHand()).safeValueInf(dto.getSafeValueInf()).intendedDepositHandInf(dto.getIntendedDepositHandInf())
                    .effectBeginDate(dto.getEffectBeginDate()).effectEndDate(dto.getEffectEndDate())
                    .oneDayCost(dto.getOneDayCost()).build();


            DepositoryBank bank = bankService.findByName(dto.getBankName());
            if (Objects.nonNull(bank)) {
                year.setBankId(bank.getId());
            }
            save(year);
        }


        return context;
    }


}
